package com.andreanaya.net
{
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	/**
	 * Dispatched when the file load is complete.
	 * 
	 * @eventType com.andreanaya.events.DataLibEvent
	 * 
	 * @see com.andreanaya.events.DataLibEvent#COMPLETE
	 */
	[Event(name="complete", type="com.andreanaya.events.DataLibEvent")]
	/**
	 * Dispatched when the file load is in progress.
	 * 
	 * @eventType com.andreanaya.events.DataLibEvent
	 * 
	 * @see com.andreanaya.events.DataLibEvent#PROGRESS
	 */
	[Event(name="progress", type="com.andreanaya.events.DataLibEvent")]
	
	/**
	 * When a the <code>addItem</code> or <code>addItemAt</code> method is called, an instance of the DataLibItem is created.
	 */
	public class DataLibItem extends EventDispatcher
	{
		private var _request:URLRequest;
		private var _type:String;
		private var _returnObject:Object;
		private var _context:LoaderContext;
		private var _bytesLoaded:uint;
		private var _bytesTotal:uint;
		private var _initied:Boolean;
		private var _loaded:Boolean;
		private var _loader:*;
		private var _data:*;
		
		/** 
		 * Creates a new DataLibItem instance.
		 */
		public function DataLibItem(request:URLRequest, type:String, returnObject:Object = null, context:LoaderContext = null):void
		{
			_request = request;
			_type = type;
			_returnObject = returnObject;
			_context = context;
			_bytesLoaded = 0;
			_bytesTotal = 0;
		}
		/** 
		 * The URLRequest created for the item.
		 */
		public function get request():URLRequest
		{
			return _request;
		}
		/** 
		 * The type of file to be loaded.
		 */
		public function get type():String
		{
			return _type;
		}
		/** 
		 * The object that will be returned when the file load is complete.
		 */
		public function get returnObject():Object
		{
			return _returnObject;
		}
		/** 
		 * The loaderContext of the item.
		 */
		public function get context():LoaderContext
		{
			return _context;
		}
		/** 
		 * Indicates if the loading process has initied.
		 */
		public function get initied():Boolean
		{
			return _initied;
		}
		/** 
		 * Indicates if the file is loaded.
		 */
		public function get loaded():Boolean
		{
			return _loaded;
		}
		/** 
		 * The number of bytes that are loaded for the file. When this number equals the value of <code>bytesTotal</code>, all of the bytes are loaded. 
		 */
		public function get bytesLoaded():int
		{
			return _bytesLoaded;
		}
		/** 
		 * The number of compressed bytes in the entire file.
		 * 
		 * <p>Before the first <code>progress</code> event is dispatched, this file <code>bytesTotal</code> is 0. After the first <code>progress</code> event from the Loader object, <code>bytesTotal</code> reflects the actual number of bytes to be downloaded.</p>
		 */
		public function get bytesTotal():int
		{
			return _bytesTotal;
		}
		/** 
		 * The loaded data of the file. If the item is not loaded this value is null.
		 */
		public function get data():*
		{
			return _data;
		}
		
		/**
		 * @private 
		 */
		internal function load():void
		{
			_initied = true;
			
			if(DataLib.getData(_request) != undefined)
			{
				_data = DataLib.getData(_request);
				
				_bytesLoaded = 1;
				_bytesTotal = 1;
				
				_loaded = true;
				
				dispatchEvent(new Event(Event.COMPLETE));
				
				return;
			}
			if(_type == DataLib.TYPE_IMAGE || type == DataLib.TYPE_SWF)
			{
				_loader = new Loader();
				
				_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
				_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
				_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
				
				_loader.load(_request, _context);
			}
			else
			{
				_loader = new URLLoader();
				
				_loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
				_loader.addEventListener(ProgressEvent.PROGRESS, onProgress);
				_loader.addEventListener(Event.COMPLETE, onComplete);
				
				if(_type == DataLib.TYPE_BINARY)
				{
					_loader.dataFormat = URLLoaderDataFormat.BINARY;
				}
				else if(type == DataLib.TYPE_TEXT)
				{
					_loader.dataFormat = URLLoaderDataFormat.TEXT;
				}
				
				_loader.load(request);
			}
		}
		/**
		 * @private 
		 */
		internal function close():void
		{
			try{
				_loader.close();
			}catch(e:Error){
				trace(e);
			}
			
			_initied = false;
		}
		private function onError(e:IOErrorEvent):void{
			trace(e)
			dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
		}
		private function onProgress(e:ProgressEvent):void
		{
			_bytesLoaded = e.bytesLoaded;
			_bytesTotal = e.bytesTotal;
			
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, _bytesLoaded, _bytesTotal));
		}
		private function onComplete(e:Event):void
		{
			if(_type == DataLib.TYPE_IMAGE || _type == DataLib.TYPE_SWF)
			{
				_data = e.currentTarget.content;
				_loader.unload();
			}
			else if(_type == DataLib.TYPE_BINARY || _type == DataLib.TYPE_TEXT)
			{
				_data = e.currentTarget.data
			}
			
			_loader = null;
			
			_loaded = true;
			
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}
}